home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / examples / demo / demosrc / d_t_series.pro < prev    next >
Text File  |  1997-07-08  |  45KB  |  1,465 lines

  1. ; $Id: d_t_series.pro,v 1.19 1997/04/20 18:44:55 tremblay Exp $
  2. ;
  3. ;  Copyright (c) 1997, Research Systems, Inc. All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5. ;
  6. ;+
  7. ;  FILE:
  8. ;       d_t_series.pro
  9. ;
  10. ;  CALLING SEQUENCE: d_t_series
  11. ;
  12. ;  PURPOSE:
  13. ;       Shows a time series as an image or a 3-D plot.
  14. ;
  15. ;  MAJOR TOPICS: Data analysis and plotting
  16. ;
  17. ;  CATEGORY:
  18. ;       IDL 5.0
  19. ;
  20. ;  INTERNAL FUNCTIONS and PROCEDURES:
  21. ;       fun TS_READ             - Read the time series file
  22. ;       fun TS_COLOR            - Define working colors
  23. ;       fun TS_SIZES            - Size the widgets
  24. ;       pro TS_SURF             - Create the surface plot
  25. ;       pro TS_MENU_EVENT       - Handle the menu events
  26. ;       fun TS_DATE             - Convert date format
  27. ;       fun TS_TIME             - Find time for the cursor location
  28. ;       fun TS_IMAGE            - Find min and max of image data set
  29. ;       pro TS_LEGEND           - Create the legend
  30. ;       pro TS_DRAW_EVENT       - Handle the drawing area event
  31. ;       pro TS_DRAW             - Create the image plot
  32. ;       pro TS_ROTATION_EVENT   - Handle the rotation slider event
  33. ;       pro TS_NON_EVENT        - Do nothing
  34. ;       pro TS_TOGGLE_EVENT     - Toggle z axis button state
  35. ;       fun TS_MONTH_STR        - convert month format
  36. ;       pro TS_MONTH_EVENT      - Handle month event slider
  37. ;       fun STRSLIDER           - Create sliders
  38. ;       pro TS_SERIESCLEANUP    - Cleanup procedure
  39. ;       pro TS_SERIES           - Main procedure
  40. ;
  41. ;  EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
  42. ;       t_series.txt
  43. ;
  44. ;  REFERENCE: IDL Reference Guide, IDL User's Guide
  45. ;
  46. ;  NAMED STRUCTURES:
  47. ;       none.
  48. ;
  49. ;  COMMON BLOCS:
  50. ;       none.
  51. ;
  52. ;  MODIFICATION HISTORY:  Written:  DF, RSI,  1995
  53. ;                         Modified by SU, RSI, January 1997
  54. ;-
  55. ;--------------------------------------------------------------------
  56. ;
  57. ;   PURPOSE : Read the time series data.
  58. ;
  59. function TS_READ, $
  60.     filename      ; IN: file name
  61.  
  62.     ;  Read in time series data
  63.     ;  called by D_T_SERIES.PRO.
  64.     ;  This function does NOT check for
  65.     ;  file existence.
  66.     ;
  67.     OPENR, lun, filename, /XDR, /GET_LUN
  68.  
  69.     ;  Read in the data type.
  70.     ;
  71.     type = 0
  72.     READU, lun, type
  73.  
  74.     ;  Read in the voltage.
  75.     ;
  76.     voltage = 0
  77.     READU, lun, voltage
  78.  
  79.     ;  Read in the number of days.
  80.     ;
  81.     n_days = 0L
  82.     READU, lun, n_days
  83.  
  84.     ;  Read in the array.
  85.     ;
  86.     array = Intarr(n_days, 48, /Nozero)
  87.     READU, lun, array
  88.  
  89.     ;  Read in the date.
  90.     ;
  91.     date = Lonarr(n_days, /Nozero)
  92.     READU, lun, date
  93.  
  94.     ;  Read in ?.
  95.     ;
  96.     miss = Bytarr(n_days, 48, /Nozero)
  97.     READU, lun, miss
  98.  
  99.     ;  Close the file.
  100.     ;
  101.     CLOSE, lun
  102.     FREE_LUN, lun
  103.  
  104.     ;  Determine the array locations of unique months.
  105.     ;
  106.     uniq_months = Uniq(date / 100L)
  107.  
  108.     ;  Determine the maximum value of the array.
  109.     ;
  110.     z_max = Max(array)
  111.  
  112.     ;  Set up the data structure.
  113.     ;
  114.     RETURN, { type:type, $
  115.         voltage:voltage, $
  116.         n_days:n_days, $
  117.         array:array, $
  118.         date:date, $
  119.         miss:miss, $
  120.         uniq_months:uniq_months, $
  121.         z_max:z_max }
  122. end   ;  of TS_READ
  123.  
  124. ;--------------------------------------------------------------------
  125. ;
  126. ;   PURPOSE : Read the time series data.
  127. ;             Define colors for time series demo
  128. ;             called by D_T_SERIES.PRO.
  129. ;             Returns a structure of integers that
  130. ;             represent color values.
  131. ;             Make sure we have these colors defined and
  132. ;             know where they are in the table.
  133. ;             Start by checking the number of colors IDL grabbed.
  134. ;
  135. function TS_COLOR
  136.     if (!D.TABLE_SIZE GT 7) then begin
  137.  
  138.         ;  Allocate bins for the defined colors to occupy.
  139.         ;
  140.         white = !D.TABLE_SIZE - 1
  141.         yellow = !D.TABLE_SIZE - 2
  142.         green = !D.TABLE_SIZE - 3
  143.         red = !D.TABLE_SIZE - 4
  144.         blue = !D.TABLE_SIZE - 5
  145.         gray = !D.TABLE_SIZE - 6
  146.         black = !D.TABLE_SIZE - 7
  147.  
  148.         ;  Ct_max is the upper bound of the remaining colors.
  149.         ;
  150.         ct_max = !D.TABLE_SIZE - 8
  151.         LOADCT, 5
  152.  
  153.         ;  Stretch the loaded color table to the new bounds.
  154.         ;
  155.         STRETCH, 0, ct_max
  156.  
  157.         ;  Define the colors and assign to appropriate bins.
  158.         ;
  159.         TVLCT, 255, 255, 255, white
  160.         TVLCT, 255, 255,   0, yellow
  161.         TVLCT,   0, 255,   0, green
  162.         TVLCT, 255,  63,  63, red
  163.         TVLCT, 127, 127, 255, blue
  164.         TVLCT,  90,  90,  90, gray
  165.         TVLCT,   0,   0,   0, black
  166.     endif else begin
  167.  
  168.         ;  If the color table is too small use
  169.         ;  two color approach.
  170.         ;
  171.         white = 1
  172.         yellow = 1
  173.         green = 1
  174.         red = 1
  175.         blue = 1
  176.         gray = 0
  177.         black = 0
  178.         ct_max = 1
  179.     endelse
  180.  
  181.     ;  Return a structure of colors.
  182.     ;
  183.     RETURN, { white:white, $
  184.           yellow:yellow, $
  185.           green:green, $
  186.           red:red, $
  187.           blue:blue, $
  188.           gray:gray, $
  189.           black:black, $
  190.           ct_max:ct_max }
  191. End
  192.  
  193. ;--------------------------------------------------------------------
  194. ;
  195. ;   PURPOSE : Set the size of the main drawing area.
  196. ;
  197. function TS_SIZES, $
  198.     sc_size        ; IN: screen size
  199.  
  200.     draw_size = [ FIX(0.75 * sc_size(0)), $
  201.                   FIX(0.60 * sc_size(1)) ]
  202.  
  203.     ;  Set the size of 2-D byte scale image.
  204.     ;
  205.     img_size = [ fix(0.50 * draw_size(0)), $
  206.              fix(0.35 * draw_size(1)) ]
  207.  
  208.     ;  Calculate the ratio of the y size of the byte.
  209.     ;  Scale plot of the data to the actual
  210.     ;  number of data points (48).
  211.     ;
  212.     ratio = ( img_size(1) / 48. )
  213.  
  214.     ;  Set the location of the 2-D byte scale image.
  215.     ;
  216.     img_loc = [ fix(0.40 * draw_size(0)), $
  217.             fix(0.57 * draw_size(1)) ]
  218.  
  219.     ;  Create the coords for the square vertical
  220.     ;  profile display box.
  221.     ;
  222.     x1_time_box = fix(0.10 * draw_size(0))
  223.     y1_time_box = img_loc(1)
  224.     y2_time_box = img_loc(1) + img_size(1)
  225.     x2_time_box = x1_time_box + (y2_time_box - y1_time_box)
  226.  
  227.     ;  Put the vertical profile box coords in vector
  228.     ;  format for use in the plot routine.
  229.     ;
  230.     time_box = [ x1_time_box, y1_time_box, $
  231.              x2_time_box, y2_time_box ]
  232.  
  233.     ;  Create an index array for plotting the time profile.
  234.     ;
  235.     time_ind = Indgen(img_size(1))
  236.  
  237.     ;  Create the coords for the rectangular
  238.     ;  horizontal profile display box.
  239.     ;
  240.     x1_date_box = img_loc(0)
  241.     x2_date_box = img_loc(0) + img_size(0)
  242.     y1_date_box = fix(0.10 * draw_size(1))
  243.     y2_date_box = y1_date_box + img_size(1)
  244.  
  245.     ;  Put the horizontal profile box coords in vector
  246.     ;  format for use in the plot routine.
  247.     ;
  248.     date_box = [ x1_date_box, y1_date_box, $
  249.              x2_date_box, y2_date_box ]
  250.  
  251.     RETURN, { draw_size:draw_size, $
  252.           img_size:img_size, $
  253.           img_loc:img_loc, $
  254.           time_box:time_box, $
  255.           date_box:date_box, $
  256.           time_ind:time_ind, $
  257.           ratio:ratio }
  258. End        ;  of TS_SIZES
  259.  
  260. ;--------------------------------------------------------------------
  261. ;
  262. ;   PURPOSE : Redraw the surface.
  263. ;
  264. pro TS_SURF, $
  265.     info       ; IN: info structure
  266.  
  267.     WIDGET_CONTROL, info.ts_base, /HOURGLASS
  268.  
  269.     WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  270.     WIDGET_CONTROL, info.m_slider_value, GET_VALUE=value
  271.  
  272.     if (value EQ '    ALL    ') then begin
  273.         surf_data = info.data
  274.     endif else begin
  275.         WIDGET_CONTROL, info.main_draw, GET_UVALUE=data, /NO_COPY
  276.         surf_data = data
  277.         WIDGET_CONTROL, info.main_draw, SET_UVALUE=data, /NO_COPY
  278.     endelse
  279.  
  280.     If (info.axis_toggle EQ 1) then begin
  281.         zrange = [ 0, info.z_max ] 
  282.     endif else begin
  283.         zrange = [ image.min_data, image.max_data ]
  284.     endelse
  285.  
  286.     top = image.max_data * info.scl_ratio
  287.     WSET, info.draw_id
  288.  
  289.     SHADE_SURF, surf_data, $
  290.         SHADES=Bytscl( surf_data, TOP=top ), $
  291.         AZ=info.az, AX=info.ax, $
  292.         CHARSIZE=1.5, TICKLEN=(-0.02), $
  293.         XSTYLE=1, XTICKS=1, $
  294.         XRANGE=[ 0, (image.n_days - 1) ], $
  295.         XTICKNAME=[ image.min_date_str, image.max_date_str ], $
  296.         YSTYLE=1, YTICKS=4, $
  297.         YTICKNAME=[ '00:00', '06:00', '12:00', '18:00', '24:00' ], $
  298.         ZRANGE=zrange, $
  299.         XTITLE='D A T E', $
  300.         YTITLE='T I M E', $
  301.         ZTITLE='M E G A W A T T S'
  302.  
  303.     WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  304. end
  305.  
  306. ;--------------------------------------------------------------------
  307. ;
  308. ;   PURPOSE :  Handle the events generated from the
  309. ;              time series menu bar.
  310. ;
  311. pro TS_MENU_EVENT, $
  312.     event         ; IN: event structure
  313.  
  314.     ;  Get the button value.
  315.     ;
  316.     WIDGET_CONTROL, event.id, GET_VALUE=value
  317.  
  318.     ;  Check for quit selection.
  319.     ;
  320.     if (value EQ 'Quit') then  begin
  321.         WIDGET_CONTROL, event.top, /DESTROY 
  322.  
  323.         ;  Check for help selection.
  324.         ;
  325.     endif else if (value EQ 'About Time Series') then begin
  326.  
  327.         If Xregistered('XDisplayFile') then RETURN
  328.         XDisplayFile, filepath('t_series.txt', $
  329.         SUBDIR=['examples','demo','demotext']), $
  330.         DONE_BUTTON='Done', $
  331.         TITLE='Time Series Help', $
  332.         GROUP=event.top, WIDTH=55, HEIGHT=14
  333.  
  334.     endif else if (value EQ '  Fixed Z Axis') then begin
  335.  
  336.         WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  337.         info.axis_toggle = 1
  338.  
  339.         If (info.display_toggle EQ 0) then begin
  340.             WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  341.             TS_DRAW, info, image
  342.             WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  343.         endif else  begin
  344.             TS_SURF, info
  345.         endelse
  346.  
  347.         WIDGET_CONTROL, info.zfixed_bttn, SET_VALUE='* Fixed Z Axis'
  348.         WIDGET_CONTROL, info.zvary_bttn,  SET_VALUE='  Variable Z Axis'
  349.         WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  350.  
  351.     endif else if (value EQ '  Variable Z Axis') then begin
  352.  
  353.         WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  354.         info.axis_toggle = 0
  355.  
  356.         If (info.display_toggle EQ 0) then begin
  357.             WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  358.             TS_DRAW, info, image
  359.             WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  360.         endif else  begin
  361.             TS_SURF, info
  362.         endelse
  363.  
  364.         WIDGET_CONTROL, info.zfixed_bttn, SET_VALUE='  Fixed Z Axis'
  365.         WIDGET_CONTROL, info.zvary_bttn,  SET_VALUE='* Variable Z Axis'
  366.         WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  367.  
  368.     endif else if (value EQ 'Surface') then begin
  369.  
  370.         WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  371.         WIDGET_CONTROL, info.wSurfaceButton, SENSITIVE=0
  372.         WIDGET_CONTROL, info.wImageButton, SENSITIVE=1
  373.         WIDGET_CONTROL, info.opt_menu, SENSITIVE=1
  374.  
  375.         WIDGET_CONTROL, info.main_draw, EVENT_PRO='TS_NON_EVENT'
  376.         WIDGET_CONTROL, info.toggle, SET_VALUE='Image'
  377.         WIDGET_CONTROL, info.wSelectionBase(0), MAP=0
  378.         WIDGET_CONTROL, info.wSelectionBase(1), MAP=1
  379.         info.display_toggle = 1
  380.  
  381.         TS_SURF, info
  382.  
  383.         WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  384.  
  385.     endif else if (value EQ 'Image') then begin
  386.         WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  387.         WIDGET_CONTROL, info.wSurfaceButton, SENSITIVE=1
  388.         WIDGET_CONTROL, info.wImageButton, SENSITIVE=0
  389.         WIDGET_CONTROL, info.opt_menu, SENSITIVE=0
  390.  
  391.         WIDGET_CONTROL, info.toggle, SET_VALUE='Surface'
  392.         WIDGET_CONTROL, info.wSelectionBase(0), MAP=1
  393.         WIDGET_CONTROL, info.wSelectionBase(1), MAP=0
  394.         WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  395.         info.display_toggle = 0
  396.  
  397.         TS_DRAW, info, image
  398.  
  399.         WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  400.         WIDGET_CONTROL, info.main_draw, EVENT_PRO='TS_DRAW_EVENT'
  401.  
  402.         WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  403.  
  404.     endif else begin
  405.         RETURN
  406.     endelse
  407.  
  408. end
  409.  
  410. ;--------------------------------------------------------------------
  411. ;
  412. ;   PURPOSE :  Convert a long integer date in the form
  413. ;              of yymmdd to a string
  414. ;              covert to the long integer to a string
  415. ;              time series menu bar.
  416. ;
  417. function TS_DATE, $
  418.     date     ; IN: long integer date
  419.  
  420.     date_str = Strtrim(String(date), 1)
  421.  
  422.     ;  Get the two year digits.
  423.     ;
  424.     year = Strmid(date_str, 0, 2)
  425.  
  426.     ;  Get the two month digits & convert to integer.
  427.     ;
  428.     index = Fix(Strmid(date_str, 2, 2))
  429.  
  430.     ;  Create a string of month names.
  431.     ;
  432.     all_months = 'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'
  433.  
  434.     ; Index into the string of month names.
  435.     ;
  436.     month = Strmid(all_months, (index - 1) * 3, 3)
  437.  
  438.     ;  Get the two day digits.
  439.     ;
  440.     day = Strmid(date_str, 4, 2)
  441.  
  442.     ;  Return a string in the form: dd mon yy.
  443.     ;
  444.     RETURN, (' ' + day + ' ' + month + ' ' + year)
  445. end
  446.  
  447. ;--------------------------------------------------------------------
  448. ;
  449. ;   PURPOSE :  Calculate the time of that the current
  450. ;              data value was taken based on the
  451. ;              the cursor location in the byte scale
  452. ;              image, y is the y axis value of the cursor.
  453. ;
  454. function TS_TIME, $
  455.     y, $          ; IN: axis value of the cursor
  456.     y_size, $     ; IN: y size of the image
  457.     ratio         ; IN: display ratio
  458.  
  459.     ;  Calculate the hour and minute of the data value
  460.     ;  (time series data were collected in half
  461.     ;  hour increments).
  462.     ;
  463.     hour = ( 24L * y ) / y_size
  464.  
  465.     ;  Minute equals either 0 or 30 since the
  466.     ;  data were taken at half hour increments.
  467.     ;
  468.     minute = (FIX( y / ratio ) mod 2L ) * 30L
  469.  
  470.     ;  Convert the variables to strings.
  471.     ;
  472.     hour_str = Strtrim( String( hour ), 2 )
  473.     min_str = Strtrim( String( minute ), 2 )
  474.  
  475.     ;  Add a 0 if necessary.
  476.     ;
  477.     If ( hour LT 10 ) Then hour_str = '0' + hour_str
  478.     If ( minute LT 10 ) Then min_str = '0' + min_str
  479.  
  480.     ;  Return a time string as HH:MM.
  481.     ;
  482.     RETURN, ' ' + hour_str + ':' + min_str
  483. end
  484.  
  485. ;--------------------------------------------------------------------
  486. ;
  487. ;   PURPOSE : Find the min and max of the data.
  488. ;
  489. function TS_IMAGE, $
  490.     data, $        ; IN: image data
  491.     date, $        ; IN: date
  492.     img_size, $    ; IN: image size
  493.     scl_ratio      ; IN: scale ratio
  494.  
  495.     min_data = Min(data)
  496.     max_data = Max(data)
  497.  
  498.     ;  Resize the time series data.
  499.     ;
  500.     img_data = CONGRID( data, img_size(0), img_size(1) )
  501.  
  502.     ;  Create the 2-D byte scale image.
  503.     ;
  504.     img_view = BYTSCL( img_data, TOP=(max_data * scl_ratio) )
  505.  
  506.     ;  Resize the date array to match the data array.
  507.     ;
  508.     img_date = CONGRID( date, img_size(0) )
  509.  
  510.     ;  Determine the first and last dates,
  511.     ;  convert them to a readable format,
  512.     ;  and add blanks for display positioning.
  513.     ;
  514.     min_date = Min(date)
  515.     max_date = Max(date)
  516.     blanks = '         '
  517.     min_date_str = blanks + TS_DATE(min_date)
  518.     max_date_str = TS_DATE(max_date) + blanks
  519.  
  520.     ;  Determine the number of days within the
  521.     ;  subset of the data.
  522.     ;
  523.     n_days = N_ELEMENTS(data) / 48
  524.  
  525.     RETURN, { img_data:img_data, $
  526.           img_view:img_view, $
  527.           img_date:img_date, $
  528.           min_data:min_data, $
  529.           max_data:max_data, $
  530.           min_date:min_date, $
  531.           max_date:max_date, $
  532.           min_date_str:min_date_str, $
  533.           max_date_str:max_date_str, $
  534.           n_days:n_days }
  535. end
  536.  
  537. ;--------------------------------------------------------------------
  538. ;
  539. ;   PURPOSE : Create the color bar legend.
  540. ;
  541. pro TS_LEGEND,  $
  542.     info, $      ; IN: info structure
  543.     image, $     ; IN: image data
  544.     legend_id, $ ; IN: legend identifier
  545.     leg_size     ; IN: legend size
  546.  
  547.     img = BINDGEN(info.ct_max + 1) # REPLICATE(1B, !D.Y_Size)
  548.  
  549.     ;  Position the color bar legend.
  550.     ;
  551.     x_leg_pos = FIX(0.50 * (leg_size(0) - (info.ct_max + 1)))
  552.  
  553.     ;  Display the color bar legend with gray background.
  554.     ;
  555.     WSET, legend_id
  556.     ERASE, info.gray
  557.     TV, img, x_leg_pos, 0
  558.  
  559.     ;  Calculate the y position of the min & max labels.
  560.     ;
  561.     y_label_pos = fix(0.50 * (leg_size(1) - !D.Y_Ch_Size))
  562.  
  563.     ;  Label the color bar legend min value.
  564.     ;
  565.     XYOUTS, (x_leg_pos - !D.Y_Ch_Size), y_label_pos, $
  566.         STRTRIM( STRING(image.min_data), 2), $
  567.         COLOR=info.white, FONT=0, ALIGNMENT=(1.0), /DEVICE
  568.  
  569.     ;  Label the color bar legend max value.
  570.     ;
  571.     XYOUTS, (x_leg_pos + info.ct_max + 1 + !D.Y_Ch_Size), $
  572.         y_label_pos, STRTRIM(STRING(image.max_data), 2), $
  573.         COLOR=info.white, FONT=0, ALIGNMENT=(0.0), /DEVICE
  574.  
  575.     EMPTY
  576. End
  577.  
  578. ;--------------------------------------------------------------------
  579. ;
  580. ;   PURPOSE : Event handler for the drawing (viewing) area.
  581. ;
  582. pro TS_DRAW_EVENT, $
  583.     event       ; IN: event structure
  584.  
  585.     WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  586.  
  587.     ;  Calculate the position of the cursor within
  588.     ;  the 2-D image box.
  589.     ;
  590.     x = event.x - info.img_loc(0)
  591.     y = event.y - info.img_loc(1)
  592.  
  593.     ;  Check to see if the cursor is out of the image box.
  594.     ;
  595.     If (x LT 0) OR (y LT 0) OR $
  596.        (x GE info.img_size(0)) OR $
  597.        (y GE info.img_size(1)) then begin
  598.         WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  599.         RETURN
  600.     endif
  601.  
  602.     WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  603.  
  604.     time_data = image.img_data(x, *)
  605.     date_data = image.img_data(*, y)
  606.  
  607.     WSET, info.draw_id
  608.     DEVICE, COPY=[ 0, 0, !D.X_Size, !D.Y_Size, $
  609.                0, 0, info.copy_id ]
  610.     EMPTY
  611.  
  612.     if (info.axis_toggle EQ 1) then  begin
  613.         data_range = [ 0, info.z_max ] 
  614.     endif else begin 
  615.         data_range = [ image.min_data, image.max_data ]
  616.     endelse
  617.  
  618.     ;  Plot the time profile data.
  619.     ;
  620.     PLOT, TEMPORARY(time_data), info.time_ind, $
  621.         XRANGE=data_range, $
  622.         YRANGE=[0, info.img_size(1) - 1], $
  623.         POSITION=info.time_box, $
  624.         XSTYLE=5, YSTYLE=5, COLOR=info.yellow, $
  625.         /NOERASE, /DEVICE
  626.  
  627.     ;  Plot the date profile data.
  628.     ;
  629.     PLOT, Temporary(date_data), $
  630.         XRANGE=[0, info.img_size(0) - 1], $
  631.         YRANGE=data_range, $
  632.         POSITION=info.date_box, $
  633.         XSTYLE=5, YSTYLE=5, COLOR=info.yellow, $
  634.         /NOERASE, /DEVICE
  635.  
  636.     ;  Calculate the x position of the data output.
  637.     ;
  638.     x_label_pos = 0.05 * info.draw_size(0) + 50
  639.  
  640.     ;  Display the date the cursor is on.
  641.     ;
  642.     XYOUTS, x_label_pos, (0.30 * info.draw_size(1)), $
  643.         TS_DATE(image.img_date(x)), $
  644.         FONT=0, /DEVICE, COLOR=info.green
  645.  
  646.     ;  Display the time the cursor is on.
  647.     ;
  648.     XYOUTS, x_label_pos, (0.20 * info.draw_size(1)), $
  649.         TS_TIME(y, info.img_size(1), info.ratio), $
  650.         FONT=0, /DEVICE, COLOR=info.green
  651.  
  652.     ;  Display the data value the cursor is on.
  653.     ;
  654.     str = ' ' + STRTRIM(String(image.img_data(x,y)),2)
  655.     XYOUTS, x_label_pos, (0.10 * info.draw_size(1)), $
  656.         str, FONT=0, /DEVICE, COLOR=info.green
  657.  
  658.     ;  Extend the vertical cross hairs into
  659.     ;  the date profile.
  660.     ;
  661.     PLOTS, [event.x, event.x], [0, !D.Y_Size], $
  662.         COLOR=info.gray, /DEVICE
  663.  
  664.     ;  Extend the horizontal cross hairs into
  665.     ;  the time profile.
  666.     ;
  667.     PLOTS, [0, !D.X_Size], [event.y, event.y], $
  668.         COLOR=info.gray, /DEVICE
  669.  
  670.     EMPTY
  671.  
  672.     WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  673.     WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  674. end
  675.  
  676. ;--------------------------------------------------------------------
  677. ;
  678. ;   PURPOSE : Create the byte scale image of the time series
  679. ;             data and the time & date profiles.
  680. ;
  681. Pro TS_DRAW, $
  682.     info, $     ; IN: info structure
  683.     image       ; IN: image
  684.  
  685.     ;  Display hourglass cursor while
  686.     ;  preparing the draw area.
  687.     ;
  688.     WIDGET_CONTROL, info.ts_base, /HOURGLASS
  689.  
  690.     ;  Set the main draw area color to gray.
  691.     ;
  692.     WSET, info.copy_id
  693.     ERASE, info.gray
  694.  
  695.     ;  Display the 2-D byte scale image.
  696.     ;
  697.     TV, image.img_view, info.img_loc(0), info.img_loc(1)
  698.  
  699.     XYOUTS, (info.img_loc(0)+info.img_size(0)/2.0), $
  700.         (info.img_loc(1)+info.img_size(1)+10), $ ; 10 : above the image
  701.         'Feeder Cicuits Power', FONT=0, $
  702.         COLOR=info.white, /DEVICE, ALIGNMENT=0.5
  703.  
  704.     ;  Create the square background for the
  705.     ;  time profile display.
  706.     ;
  707.     POLYFILL, [ info.time_box(0), info.time_box(2),  $
  708.         info.time_box(2), info.time_box(0) ], $
  709.         [ info.time_box(1), info.time_box(1),  $
  710.         info.time_box(3), info.time_box(3) ], $
  711.         /DEVICE, T3D=0, COLOR=info.black
  712.  
  713.     ;  Create the rectangular background for the
  714.     ;  date profile display.
  715.     ;
  716.     POLYFILL, [ info.date_box(0), info.date_box(2),  $
  717.         info.date_box(2), info.date_box(0) ], $
  718.         [ info.date_box(1), info.date_box(1),  $
  719.         info.date_box(3), info.date_box(3) ], $
  720.         /DEVICE, T3D=0, COLOR=info.black
  721.  
  722.     if (info.axis_toggle EQ 1) then begin
  723.         data_range = [ 0, info.z_max ] 
  724.     endif else begin  
  725.         data_range = [ image.min_data, image.max_data ]
  726.     endelse
  727.  
  728.     ;  Draw the blue grid for the time profile box
  729.     ;
  730.     PLOT, [0, 0], [0, info.img_size(1)],  /DEVICE, $
  731.         XRANGE=data_range, $
  732.         YRANGE=[0, info.img_size(1)], $
  733.         POSITION=info.time_box, $
  734.         XTICKS=2, YTICKS=2, TICKLEN=1.0, XMINOR=1, $
  735.         YTICKNAME=['00:00', '12:00', '24:00'], $
  736.         XSTYLE=1, YSTYLE=1, XGRIDSTYLE=1, YGRIDSTYLE=1, $
  737.         COLOR=info.blue, FONT=0, /NODATA, /NOERASE
  738.  
  739.     ;  Draw the white time profile box.
  740.     ;
  741.     PLOT, [0, 0], [0, info.img_size(1)],  /DEVICE, $
  742.         TITLE='Time Profile', XTITLE='MW', $
  743.         XRANGE=data_range, $
  744.         YRANGE=[0, info.img_size(1)], $
  745.         POSITION=info.time_box, $
  746.         XTICKS=2, YTICKS=2, TICKLEN=0.0, XMINOR=1, $
  747.         YTICKNAME=['00:00', '12:00', '24:00'], $
  748.         XSTYLE=1, YSTYLE=1, XGRIDSTYLE=1, YGRIDSTYLE=1, $
  749.         COLOR=info.white, FONT=0, /NODATA, /NOERASE
  750.  
  751.     ;  Draw the blue grid for the date profile box.
  752.     ;
  753.     PLOT, [0, info.img_size(0)], [0, 0], /DEVICE, $
  754.         XRANGE=[0, info.img_size(0)], $
  755.         YRANGE=data_range, $
  756.         POSITION=info.date_box, $
  757.         XTICKS=1, TICKLEN=1.0, YMINOR=1, $
  758.         XTICKNAME=[image.min_date_str, image.max_date_str], $
  759.         XSTYLE=1, YSTYLE=1, XGRIDSTYLE=1, YGRIDSTYLE=1, $
  760.         COLOR=info.blue, FONT=0, /NOERASE
  761.  
  762.     ;  Draw the white date profile box.
  763.     ;
  764.     PLOT, [0, info.img_size(0)], [0, 0], /DEVICE, $
  765.         TITLE='Date Profile', YTITLE='MW', $
  766.         XRANGE=[0, info.img_size(0)], $
  767.         YRANGE=data_range, $
  768.         POSITION=info.date_box, $
  769.         XTICKS=1, TICKLEN=0.0, Yminor=1, $
  770.         XTICKNAME=[image.min_date_str, image.max_date_str], $
  771.         XSTYLE=1, YSTYLE=1, XGRIDSTYLE=1, YGRIDSTYLE=1, $
  772.         COLOR=info.white, FONT=0, /NOERASE
  773.  
  774.     ;  Draw the date, time, and data value labels.
  775.     ;
  776.     XYOUTS, 0.05, 0.30, 'DATE:', FONT=0, $
  777.         COLOR=info.white, /NORMAL
  778.     XYOUTS, 0.05, 0.20, 'TIME:', FONT=0, $
  779.         COLOR=info.white, /NORMAL
  780.     XYOUTS, 0.05, 0.10, 'DATA:', FONT=0, $
  781.         COLOR=info.white, /NORMAL
  782.  
  783.     EMPTY
  784.  
  785.     WSET, info.draw_id
  786.     DEVICE, COPY=[ 0, 0, !D.X_Size, !D.Y_Size, $
  787.                0, 0, info.copy_id ]
  788.     EMPTY
  789. end
  790.  
  791. ;--------------------------------------------------------------------
  792. ;
  793. ;   PURPOSE : Handle the events from the X & Z
  794. ;             rotation slider bars for the time
  795. ;             series surface plot.
  796. ;
  797. pro TS_ROTATION_EVENT, $
  798.     event              ; IN: event structure
  799.  
  800.     ;  Get info from the ts_base widget.
  801.     ;
  802.     WIDGET_CONTROL, event.top, GET_UVALUE=info, /No_copy
  803.  
  804.     ;  Get the string id of the slider bar.
  805.     ;
  806.     WIDGET_CONTROL, event.id, GET_UVALUE=uvalue
  807.  
  808.     ;  Get the current slider bar value.
  809.     ;
  810.     WIDGET_CONTROL, event.id, GET_VALUE=value
  811.  
  812.     ;  Check to see which rotation slider bar
  813.     ;  generated the event and modify the
  814.     ;  value that info holds on to.
  815.     ;
  816.     If (uvalue EQ 'z_slider') then begin
  817.         info.az = value 
  818.     endif else begin       ; 'x_slider'
  819.         info.ax = value
  820.     endelse
  821.  
  822.     ;  Replot the time series surface.
  823.     ;
  824.     TS_SURF, info
  825.  
  826.     ;  Replace info back into the ts_base widget.
  827.     ;
  828.     WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  829. end
  830.  
  831. ;--------------------------------------------------------------------
  832. ;
  833. ;   PURPOSE :  Handle the no event
  834. ;
  835. pro TS_NON_EVENT, $
  836.     event         ; IN: event structure
  837.  
  838. end
  839.  
  840. ;--------------------------------------------------------------------
  841. ;
  842. ;   PURPOSE :  Handle Surface/Image button event.
  843. ;
  844. pro TS_TOGGLE_EVENT, $
  845.     event         ; IN: event structure
  846.  
  847.     WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  848.  
  849.     WIDGET_CONTROL, event.id, GET_VALUE=value
  850.  
  851.     if (value EQ 'Surface') then begin
  852.         WIDGET_CONTROL, info.main_draw, EVENT_PRO='TS_NON_EVENT'
  853.         WIDGET_CONTROL, event.id, SET_VALUE='Image'
  854.         WIDGET_CONTROL, info.wSelectionBase(0), MAP=0
  855.         WIDGET_CONTROL, info.wSelectionBase(1), MAP=1
  856.         WIDGET_CONTROL, info.wSurfaceButton, SENSITIVE=0
  857.         WIDGET_CONTROL, info.opt_menu, SENSITIVE=1
  858.         WIDGET_CONTROL, info.wImageButton, SENSITIVE=1
  859.         info.display_toggle = 1
  860.  
  861.         TS_SURF, info
  862.  
  863.     endif else begin                 
  864.         WIDGET_CONTROL, event.id, SET_VALUE='Surface'
  865.         WIDGET_CONTROL, info.wSelectionBase(0), MAP=1
  866.         WIDGET_CONTROL, info.wSelectionBase(1), MAP=0
  867.         WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  868.         WIDGET_CONTROL, info.wSurfaceButton, SENSITIVE=1
  869.         WIDGET_CONTROL, info.opt_menu, SENSITIVE=0
  870.         WIDGET_CONTROL, info.wImageButton, SENSITIVE=0
  871.         info.display_toggle = 0
  872.  
  873.         TS_DRAW, info, image
  874.  
  875.         WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  876.         WIDGET_CONTROL, info.main_draw, EVENT_PRO='TS_DRAW_EVENT'
  877.     endelse
  878.  
  879.     WIDGET_CONTROL, event.top, SET_UVALUE=info, /No_copy
  880. end
  881.  
  882. ;--------------------------------------------------------------------
  883. ;
  884. ;   PURPOSE :  Convert a long integer date in the form
  885. ;              of yymmdd to a string
  886. ;              covert to the long integer to a string
  887. ;
  888. function TS_MONTH_STR, $
  889.     date       ; IN: long integer date
  890.  
  891.     date_str = Strtrim(String(date), 1)
  892.  
  893.     ;  Get the two year digits.
  894.     ;
  895.     year = STRMID(date_str, 0, 2)
  896.  
  897.     ;  Get the two month digits & convert to integer.
  898.     ;
  899.     index = FIX(Strmid(date_str, 2, 2))
  900.  
  901.     ;  Create a string of month names.
  902.     ;
  903.     all_months = 'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'
  904.  
  905.     ;  Index into the string of month names.
  906.     ;
  907.     month = STRMID(all_months, (index - 1) * 3, 3)
  908.  
  909.     ;  Return a string in the form: mon yy
  910.     ;  pad with spaces because of alignment bug.
  911.     ;
  912.     RETURN, (' ' + month + ' ' + year + ' ')
  913. end
  914.  
  915. ;--------------------------------------------------------------------
  916. ;
  917. ;   PURPOSE :  Handle the events from the STRSLIDER
  918. ;              allow the user to select which month to
  919. ;              display data from.
  920. ;
  921. pro TS_MONTH_EVENT, $
  922.     event         ; IN: event structure
  923.  
  924.     WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
  925.     WIDGET_CONTROL, info.draw_base, GET_UVALUE=image, /NO_COPY
  926.  
  927.     ;  If slider value is 0 then use data from all months
  928.     ;  else use data from a specific month.
  929.     ;
  930.     If (event.value EQ 0) then begin
  931.         WIDGET_CONTROL, info.m_slider_value, SET_VALUE='    ALL    '
  932.         image = TS_IMAGE(info.data, info.date, $
  933.             info.img_size, info.scl_ratio)
  934.     endif else begin
  935.         date = info.date(info.uniq_months(event.value - 1))
  936.         WIDGET_CONTROL, info.m_slider_value, $
  937.             SET_VALUE=TS_MONTH_STR(date)
  938.  
  939.         month = (date / 100L) * 100L
  940.  
  941.         if (event.value LT N_ELEMENTS(info.uniq_months)) then begin
  942.             next_date = info.date(info.uniq_months(event.value))
  943.             next_month = (next_date / 100L) * 100L
  944.             index = WHERE(info.date GT month AND $
  945.                 info.date LT next_month)
  946.         endif else begin
  947.             index = WHERE(info.date GT month)
  948.         endelse
  949.  
  950.         days = info.date(index)
  951.         new_data = info.data(index, *)
  952.  
  953.         image = TS_IMAGE(new_data, days, $
  954.             info.img_size, info.scl_ratio)
  955.  
  956.         WIDGET_CONTROL, info.main_draw, SET_UVALUE=new_data, /NO_COPY
  957.     endelse
  958.  
  959.     if (info.display_toggle EQ 0) then begin
  960.         TS_DRAW, info, image
  961.         WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  962.     endif else begin
  963.         WIDGET_CONTROL, info.draw_base, SET_UVALUE=image, /NO_COPY
  964.         TS_SURF, info
  965.     endelse
  966.  
  967.     WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
  968. end
  969.  
  970. ;--------------------------------------------------------------------
  971. ;
  972. ;   PURPOSE :  Create a compound slider widget with the
  973. ;              slider value centered above the slider bar
  974. ;              and the title centered under the bar.
  975. ;              the slider value can be displayed as a string
  976. ;
  977. function STRSLIDER, $
  978.     parent, $                  ; IN: parent identifer
  979.     Value=value, $             ; IN: (opt) value
  980.     Title=title, $             ; IN: (opt) title
  981.     Minimum=minimum, $         ; IN: (opt) minimum value
  982.     Maximum=maximum, $         ; IN: (opt) maximum value
  983.     Event_Pro=event_pro, $     ; IN: (opt) slider event handler
  984.     XOffset=xoffset, $         ; IN: (opt) x offset
  985.     YOffset=yoffset, $         ; IN: (opt) y offset
  986.     Slider_Value=slider_value  ; IN: (opt) slider value id
  987.  
  988.     ;  Make sure a parent id has been supplied.
  989.     ;
  990.     if (N_Params() EQ 0) then $
  991.         Message, "STRSLIDER: parent widget id required."
  992.  
  993.     ;  Check the initial value.
  994.     ;
  995.     if (N_ELEMENTS(value) NE 1) then value = 0
  996.  
  997.     ;  Check the initial value.
  998.     ;
  999.     If N_ELEMENTS(title) NE 1 Then title = ' '
  1000.  
  1001.     ;  Check the minimum and maximum values.
  1002.     ;
  1003.     If N_ELEMENTS(minimum) NE 1 Then minimum = 0
  1004.     If N_ELEMENTS(maximum) NE 1 Then maximum = 1
  1005.  
  1006.     ;  Check for max < min.
  1007.     ;
  1008.     if (maximum LE minimum) then $
  1009.       Message, "STRSLIDER: maximum value < minimum value."
  1010.  
  1011.     ;  Check for an event procedure.
  1012.     ;
  1013.     if (N_ELEMENTS(event_pro) NE 1) then $
  1014.       Message, "STRSLIDER: event procedure is required."
  1015.  
  1016.     ;  Check the offsets.
  1017.     ;
  1018.     if N_ELEMENTS(xoffset) NE 1 then xoffset = 0
  1019.     if N_ELEMENTS(yoffset) NE 1 then yoffset = 0
  1020.  
  1021.     ;  Create the base for the CW.
  1022.     ;
  1023.     slider_base = WIDGET_BASE(parent, $
  1024.         XOFFSET=xoffset, $
  1025.         YOFFSET=yoffset, $
  1026.         /BASE_ALIGN_CENTER, $
  1027.         /COLUMN )
  1028.  
  1029.     ;  Create the slider value label.
  1030.     ;
  1031.     slider_value = WIDGET_LABEL(slider_base, $
  1032.         VALUE=value, /ALIGN_CENTER)
  1033.  
  1034.     ;  Create the actual slider bar.
  1035.     ;
  1036.     slider_bar = WIDGET_SLIDER(slider_base, $
  1037.         EVENT_PRO=event_pro, /SUPPRESS_VALUE, $
  1038.         MINIMUM=minimum, MAXIMUM=maximum)
  1039.  
  1040.     ;  Create the title for the slider bar.
  1041.     ;
  1042.     slider_title = WIDGET_LABEL(slider_base, VALUE=title)
  1043.  
  1044.     Return, slider_base
  1045. End
  1046.  
  1047. ;--------------------------------------------------------------------
  1048. ;
  1049. ;  Purpose :  Cleanup procedure, restore the previous color table.
  1050. ;  
  1051. pro Quit_Event, $
  1052.     sEvent
  1053.  
  1054.     ;  Quit the application using the close box.
  1055.     ;
  1056.     if (TAG_NAMES(sEvent, /STRUCTURE_NAME) EQ $
  1057.         'WIDGET_KILL_REQUEST') then begin
  1058.         WIDGET_CONTROL, sEvent.top, /DESTROY
  1059.         RETURN
  1060.     endif
  1061. end
  1062.  
  1063. ;--------------------------------------------------------------------
  1064. ;
  1065. ;  Purpose :  Cleanup procedure, restore the previous color table.
  1066. ;  
  1067. pro T_SeriesCleanup, wTopBase
  1068.  
  1069.     ;  Get the color table saved in the window's user value
  1070.     ;
  1071.     WIDGET_CONTROL, wTopBase, GET_UVALUE=Info, /NO_COPY
  1072.  
  1073.     ;  Restore the previous color table.
  1074.     ;
  1075.     TVLCT, Info.colorTable
  1076.  
  1077.     if WIDGET_INFO(Info.groupBase, /VALID_ID) then $
  1078.         WIDGET_CONTROL, Info.groupBase, /MAP
  1079.  
  1080. end   ; of T_SeriesCleanup
  1081.  
  1082. ;----------------------------------------------------------
  1083. ;
  1084. ;  Purpose :  Display a time series (Images , plot).
  1085. ;  
  1086. ;  Description :
  1087. ;         Modified version of the time series analysis
  1088. ;         procedure in the IDL 4.0.1 Demo.
  1089. ;         Just one data set is used: 16 Megawatt, 660 Volts.
  1090. ;         It also reduces the number of windows involved in
  1091. ;         the demo (just one that toggles between the image
  1092. ;         and surface displays).
  1093. ;
  1094. pro D_T_SERIES, $
  1095.     GROUP=group, $  ; IN: (opt) group identifer
  1096.     APPTLB=appTLB   ; IN: (opt) Top level base of this main procedure
  1097.  
  1098.     ;  Check the validity of the group identifier.
  1099.     ;
  1100.     ngroup = N_ELEMENTS(group)
  1101.     if (ngroup NE 0) then begin
  1102.         check = WIDGET_INFO(group, /VALID_ID)
  1103.         if (check NE 1) then begin
  1104.             print,'Error, the group identifier is not valid'
  1105.             print, 'Return to the main application'
  1106.             RETURN
  1107.         endif
  1108.         groupBase = group
  1109.     endif else groupBase = 0L
  1110.  
  1111.     ;  Get the current color table. It will be restored when exiting.
  1112.     ;
  1113.     TVLCT, savedR, savedG, savedB, /GET
  1114.     colorTable = [[savedR],[savedG],[savedB]]
  1115.  
  1116.     ;  Make sure this program is not already running.
  1117.     ;
  1118.     if (Xregistered('D_T_SERIES')) then RETURN
  1119.  
  1120.     ;  Check for the existence of the data file.
  1121.     ;
  1122.     filename = filepath('mgwt6616.dat', $
  1123.         SUBDIR=['examples','demo','demodata'])
  1124.     found = Findfile(filename)
  1125.     if (found(0) EQ '') then begin
  1126.         error = Widget_Message($
  1127.             ['You must install the time series data', $
  1128.              'before you can run this demonstration.'], $
  1129.             /Error)
  1130.         RETURN
  1131.     endif
  1132.  
  1133.     ;  Initialize the graphics by creating a
  1134.     ;  non-visible (pixmap) window and deleting it.
  1135.     ;
  1136.     WINDOW, /FREE, /PIXMAP, XSIZE=100, YSIZE=100
  1137.     WDELETE
  1138.  
  1139.     ;  Load the data.
  1140.     ;
  1141.     data = TS_READ(filename)
  1142.  
  1143.     ;  Make the system to have a maximum of 256 colors.
  1144.     ;
  1145.     numcolors = !D.N_COLORS
  1146.  
  1147.     if ((( !D.NAME EQ 'X') OR (!D.NAME EQ 'MAC')) $
  1148.        AND (!D.N_COLORS GE 256L)) then begin
  1149.        DEVICE, PSEUDO_COLOR=8
  1150.     endif
  1151.  
  1152.     DEVICE, DECOMPOSED=0, BYPASS_TRANSLATION = 0
  1153.  
  1154.     ;  Create custom color table.
  1155.     ;
  1156.     colors = TS_COLOR()
  1157.  
  1158.     ;  Determine monitor resolution.
  1159.     ;
  1160.     Device, Get_Screen=sc_size
  1161.  
  1162.     ;  Set the size and locations of plots, etc,
  1163.     ;  Within the draw area.
  1164.     ;
  1165.     sizes = TS_SIZES(sc_size)
  1166.  
  1167.     ;  Create the top level base.
  1168.     ;
  1169.     if (N_ELEMENTS(group) EQ 0) then begin
  1170.         ts_base = $
  1171.             WIDGET_BASE( $
  1172.             TITLE='Time Series: Feeder Cicuits Power in Megawatts', $
  1173.             TLB_FRAME_ATTR=1, $
  1174.             /TLB_KILL_REQUEST_EVENTS, $
  1175.             SPACE=1, XPAD=1, YPAD=1, /COLUMN, MBAR=mbar)
  1176.     endif else begin
  1177.         ts_base = $
  1178.             WIDGET_BASE( $
  1179.             TITLE='Time Series: Feeder Cicuits Power in Megawatts', $
  1180.             GROUP_LEADER=group, $
  1181.             /TLB_KILL_REQUEST_EVENTS, $
  1182.             TLB_FRAME_ATTR=1, $
  1183.             SPACE=1, XPAD=1, YPAD=1, /COLUMN, MBAR=mbar)
  1184.     endelse
  1185.  
  1186.         ;  Create the "File" menu.
  1187.         ;
  1188.         file_menu = WIDGET_BUTTON(mbar, Value='File', /MENU)
  1189.  
  1190.         ;  Create the quit button.
  1191.         ;
  1192.         quit_bttn = WIDGET_BUTTON(file_menu, VALUE='Quit', $
  1193.             EVENT_PRO='TS_MENU_EVENT')
  1194.  
  1195.         ;  Create the "Options" menu.
  1196.         ;
  1197.         opt_menu = WIDGET_BUTTON(mbar, Value='Options', /MENU)
  1198.  
  1199.             ;  Create the z axis range buttons which
  1200.             ;  tell the surface routine to use a
  1201.             ;  fixed z axis or to let it vary as the
  1202.             ;  months change.
  1203.             ;
  1204.             zfixed_bttn = WIDGET_BUTTON(opt_menu, $
  1205.                 VALUE='  Fixed Z Axis', EVENT_PRO='TS_MENU_EVENT')
  1206.  
  1207.             zvary_bttn = WIDGET_BUTTON(opt_menu, $
  1208.                 VALUE='* Variable Z Axis', EVENT_PRO='TS_MENU_EVENT')
  1209.  
  1210.         ;  Create the View menu.
  1211.         ;
  1212.         wViewButton= WIDGET_BUTTON(mbar, Value='View', /MENU)
  1213.  
  1214.             wSurfaceButton = WIDGET_BUTTON(wViewButton, $
  1215.                 VALUE='Surface', EVENT_PRO='TS_MENU_EVENT')
  1216.  
  1217.             wImageButton = WIDGET_BUTTON(wViewButton, $
  1218.                 VALUE='Image', EVENT_PRO='TS_MENU_EVENT')
  1219.  
  1220.         ;  Create the "Help" menu.
  1221.         ;
  1222.         help_menu = WIDGET_BUTTON(mbar, VALUE='About', /HELP, /MENU)
  1223.  
  1224.             ;  Create the help button.
  1225.             ;
  1226.             help_bttn = WIDGET_BUTTON(help_menu, $
  1227.                 VALUE='About Time Series', $
  1228.                 EVENT_PRO='TS_MENU_EVENT')
  1229.  
  1230.         ;  Create the drawing area within the ts_base.
  1231.         ;
  1232.         draw_base = WIDGET_BASE(ts_base, SPACE=1, XPAD=1, YPAD=1)
  1233.  
  1234.             ;  Create the main drawing area.
  1235.             ;
  1236.             main_draw = WIDGET_DRAW(draw_base, $
  1237.                 XSIZE=sizes.draw_size(0), $
  1238.                 YSIZE=sizes.draw_size(1), $
  1239.                 EVENT_PRO='TS_DRAW_EVENT', $
  1240.                 /MOTION_EVENTS, $
  1241.                 RETAIN=2 )
  1242.  
  1243.             ;  Create the main drawing area in memory.
  1244.             ;
  1245.             copy_draw = WIDGET_DRAW(draw_base, $
  1246.                 XSIZE=sizes.draw_size(0), $
  1247.                 YSIZE=sizes.draw_size(1), $
  1248.                 RETAIN=2 )
  1249.   
  1250.         ;  Create the bottom area of the top level base
  1251.         ;
  1252.         bottom_ysize = 4 * !D.Y_Ch_Size
  1253.         bottom_base = WIDGET_BASE(ts_base, /ROW, $
  1254.             /BASE_ALIGN_CENTER)
  1255.     
  1256.             ;  Create a base for the toggle button.
  1257.             ;
  1258.             toggleBase = WIDGET_BASE(bottom_base, $
  1259.                /BASE_ALIGN_CENTER, /ROW)
  1260.  
  1261.                 ;  Create the image / surface toggle button.
  1262.                 ;
  1263.                 toggle = WIDGET_BUTTON( toggleBase, $
  1264.                     EVENT_PRO='TS_TOGGLE_EVENT', $
  1265.                     VALUE='Surface' )
  1266.  
  1267.             ;  Create a base for the month slider.
  1268.             ;
  1269.             mSliderBase = WIDGET_BASE(bottom_base, /COLUMN)
  1270.  
  1271.                 ;  Create month slider bar.
  1272.                 ;
  1273.                 m_slider = STRSLIDER( mSliderbase, $
  1274.                     EVENT_PRO='TS_MONTH_EVENT', $
  1275.                     MINIMUM=0, $
  1276.                     MAXIMUM=N_Elements(data.uniq_months), $
  1277.                     VALUE='    ALL    ', $
  1278.                     TITLE='Month', $
  1279.                     SLIDER_VALUE=m_slider_value )
  1280.  
  1281.             ;  Create a base for the surface or image options
  1282.             ;
  1283.             wSelectionBase = LONARR(2)   ; 2 is the number of selections
  1284.             wTempBase = WIDGET_BASE(bottom_base)
  1285.  
  1286.                 ;  Put the selection bases into the temporary (temp)
  1287.                 ;  base. This way, the selection bases overlaps each
  1288.                 ;  another. When the user select from the toggle button,
  1289.                 ;  (Surface / image), 
  1290.                 ;  only one selection base is mapped.
  1291.                 ;
  1292.                 for i=0, N_ELEMENTS(wSelectionbase)-1 do  begin
  1293.                     wSelectionbase(i) = WIDGET_BASE(wTempBase, $
  1294.                     UVALUE=0L, /COLUMN, MAP=0)
  1295.                 endfor
  1296.  
  1297.                     ;  Create the base for rotation slider bars.
  1298.                     ;  Use the same offsets as the legend area.
  1299.                     ;
  1300.                     rot_base = WIDGET_BASE(wSelectionBase(1), /ROW)
  1301.  
  1302.                         ;  Create the z rotation slider bar
  1303.                         ;  for the surface plot.
  1304.                         ;
  1305.                         z_base = WIDGET_BASE(rot_base, /COLUMN)
  1306.  
  1307.                             z_slider = WIDGET_SLIDER(z_base, $
  1308.                                 EVENT_PRO='TS_ROTATION_EVENT', $
  1309.                                 MINIMUM=0, $
  1310.                                 MAXIMUM=90, $
  1311.                                 VALUE=15, $
  1312.                                 UVALUE='z_slider', $
  1313.                                 TITLE='    Z Rotation' )
  1314.  
  1315.                         ;  Create the z rotation slider bar
  1316.                         ;  for the surface plot.
  1317.                         ;
  1318.                         x_base = WIDGET_BASE(rot_base, /COLUMN)
  1319.                             x_slider = WIDGET_SLIDER(x_base, $
  1320.                                 EVENT_PRO='TS_ROTATION_EVENT', $
  1321.                                 MINIMUM=0, $
  1322.                                 MAXIMUM=90, $
  1323.                                 VALUE=60, $
  1324.                                 UVALUE='x_slider', $
  1325.                                 TITLE='    X Rotation' )
  1326.  
  1327.                     ;  Set the legend area offset.
  1328.                     ;
  1329.                     leg_offset = [ FIX(0.40 * sizes.draw_size(0)), $
  1330.                                    FIX(0.10 * bottom_ysize) ]
  1331.  
  1332.                     ;  Create the legend base (so it can be unmapped).
  1333.                     ;
  1334.                     legend_base = WIDGET_BASE(wSelectionBase(0), /ROW)
  1335.  
  1336.                         ;  Set the size of the legend area.
  1337.                         ;
  1338.                         leg_size = [ FIX(0.65 * sizes.draw_size(0)), $
  1339.                                      FIX(0.80 * bottom_ysize) ]
  1340.  
  1341.                         ;  Create the legend area.
  1342.                         ;
  1343.                         legend_draw = WIDGET_DRAW(legend_base, $
  1344.                             XSIZE=leg_size(0), $
  1345.                             YSIZE=leg_size(1), $
  1346.                             RETAIN=2 )
  1347.  
  1348.     ;  Realize the time series base.
  1349.     ;
  1350.     WIDGET_CONTROL, ts_base, /REALIZE
  1351.  
  1352.     ;  Returns the top level base to the APPTLB keyword.
  1353.     ;
  1354.     appTLB = ts_Base
  1355.  
  1356.     ;  Map the surface option base as default.
  1357.     ;
  1358.     WIDGET_CONTROL, wSelectionBase(0), MAP=1
  1359.  
  1360.     ;  Get the id of the display seen on screen.
  1361.     ;
  1362.     WIDGET_CONTROL, main_draw, GET_VALUE=draw_id
  1363.  
  1364.     ;  Get the id of the display seen on screen.
  1365.     ;
  1366.     WIDGET_CONTROL, copy_draw, GET_VALUE=copy_id
  1367.  
  1368.     ;  Get the id of the legend area.
  1369.     ;
  1370.     WIDGET_CONTROL, legend_draw, GET_VALUE=legend_id
  1371.  
  1372.     ;  Scale ratio is used to make sure that the
  1373.     ;  TOP keyword is set so that a data value
  1374.     ;  always gets the same color shade.
  1375.     ;
  1376.     scl_ratio = float(colors.ct_max) / float(data.z_max)
  1377.  
  1378.     ;  Create the 2-D byte scale image.
  1379.     ;
  1380.     image = TS_IMAGE(data.array, data.date, $
  1381.         sizes.img_size, scl_ratio)
  1382.  
  1383.     ;  Create a structure that contains all the
  1384.     ;  info needed by the subroutines and event
  1385.     ;  handlers.
  1386.     ;
  1387.     info = { data:data.array, $            ; Time series data set
  1388.          date:data.date, $                 ; Dates
  1389.          z_max:data.z_max, $               ; Maximum of time series
  1390.          uniq_months:data.uniq_months, $   ; Each months
  1391.          ct_max:colors.ct_max, $           ; Number of colors
  1392.          white:colors.white, $             ; Color indices
  1393.          yellow:colors.yellow, $
  1394.          green:colors.green, $
  1395.          red:colors.red, $
  1396.          blue:colors.blue, $
  1397.          gray:colors.gray, $
  1398.          black:colors.black, $
  1399.          draw_size:sizes.draw_size, $      ; Drawing area size
  1400.          img_size:sizes.img_size, $        ; Image size
  1401.          img_loc:sizes.img_loc, $          ; Image location
  1402.          time_box:sizes.time_box, $        ; Size of time box
  1403.          date_box:sizes.date_box, $        ; Size of date box
  1404.          time_ind:sizes.time_ind, $        ; Size of time index frame
  1405.          ratio:sizes.ratio, $              ; Size ratio of data set
  1406.          ts_base:ts_base, $                ; Top level base ID
  1407.          draw_base:draw_base, $            ; Draw base ID
  1408.          legend_base:legend_base, $        ; Legen base ID
  1409.          rot_base:rot_base, $              ; Rotation base ID
  1410.          main_draw:main_draw, $            ; Main draw windget ID
  1411.          draw_id:draw_id, $                ; Secondary draw windget ID
  1412.          copy_id:copy_id, $                ; Copy widget draw ID
  1413.          zfixed_bttn:zfixed_bttn, $        ; Flag for fixed 
  1414.          zvary_bttn:zvary_bttn, $          ; Variable z aixis button ID
  1415.          m_slider_value:m_slider_value, $  ; Month slider ID
  1416.          ax:60, az:15, $                   ; Initial rotation of x and z aixes
  1417.          scl_ratio:scl_ratio, $            ; Color/data scale ratio
  1418.          axis_toggle:0, $                  ; Z axis: 0 = fixed, 1=variable
  1419.          ColorTable: colorTable, $         ; Color table to restore
  1420.          WSelectionBase: wSelectionBase, $ ; Selection base ID
  1421.          WSurfaceButton: wSurfaceButton, $ ; Button IDs
  1422.          WImageButton: wImageButton, $
  1423.          Toggle: toggle, $                
  1424.          opt_menu: opt_menu, $             
  1425.          display_toggle:0, $               ; display: 0 = image, 1 = surface
  1426.          groupBase: groupBase $            ; Base of Group Leader
  1427.     }
  1428.  
  1429.     ;  Create & draw the color bar legend.
  1430.     ;
  1431.     TS_LEGEND, info, image, legend_id, leg_size
  1432.  
  1433.     ;  Draw the byte scale image and the
  1434.     ;  date & time profiles of the data.
  1435.     ;
  1436.     TS_DRAW, info, image
  1437.  
  1438.     ;  Store the image info separate from the
  1439.     ;  info structure so it can be changed
  1440.     ;  by the month slider event handler.
  1441.     ;
  1442.     WIDGET_CONTROL, draw_base, Set_UVALUE=image
  1443.  
  1444.     ;  Store the image info in the top level base.
  1445.     ;
  1446.     WIDGET_CONTROL, ts_base, SET_UVALUE=info, /NO_COPY
  1447.  
  1448.     ;  Place the cursor on the image by default.
  1449.     ;
  1450.     TVCRS, sizes.img_loc(0) + 20, sizes.img_loc(1) + 20 
  1451.  
  1452.     ;  Desensitize the image button.
  1453.     ;  and the option menu
  1454.     ;
  1455.     WIDGET_CONTROL, wImageButton, SENSITIVE=0
  1456.     WIDGET_CONTROL, opt_menu, SENSITIVE=0
  1457.  
  1458.     ;  Tell the window manager about time series.
  1459.     ;
  1460.     XMANAGER, 'D_T_SERIES', ts_base, $
  1461.         /NO_BLOCK, $
  1462.         EVENT_HANDLER='Quit_Event', $
  1463.         CLEANUP='T_SeriesCleanup'
  1464. End
  1465.